package de.recipeminer.persistence;

import com.db4o.ObjectSet;
import de.recipeminer.environments.ExecutionContextProvider;
import org.apache.log4j.Logger;

/**
 * A collection of utility methods for isolated operations on Db4oContainers that can not be
 * grouped to instance methods of classes with more specific purpose.
 *
 * @author Markus Ackermann
 */
public class Db4oHelpers {
    private static Logger logger = Logger.getLogger(Db4oHelpers.class);

    /**
     * Tests whether there is at most one instance of the given class saved in the database of
     * the current context (conforming the Singleton contract). If there is a single instance saved, 
     * returns that instance
     * 
     *
     * @param class_ class to check for singletonness
     * @return the singleton instance, if a singleton instance is saved in the {@link Db4oContainer}
     * @throws IllegalStateException if more than one instance of {@code class_} is present in the
     *         {@code Db4oContainer}
     */
    public static <T> T getPersistedSingletonInstance(Class<T> class_) {
        return getPersistedSingletonInstance(class_, currentDatabase());
    }

    public static Db4oContainer currentDatabase() {
        return ExecutionContextProvider.currentContainer();
    }

    /**
     * Tests whether there is at most one instance of the given class saved in the given {@link Db4oContainer}
     * (conforming the Singleton contract). If there is a single instance saved,
     * returns that instance
     *
     *
     * @param class_ class to check for singletonness
     * @param container {@code Db4oContainer} to search in/verify singletonness in
     * @return the singleton instance, if a singleton instance is saved in the {@link Db4oContainer}
     * @throws IllegalStateException if more than one instance of {@code class_} is present in the
     *         {@code Db4oContainer}
     */
    public static <T> T getPersistedSingletonInstance(Class<T> class_, Db4oContainer container) {
        ObjectSet<T> objects = container.query(class_);
        if (objects.size() == 0)
            return null;
        else if (objects.size() > 1)
            throw new IllegalStateException(String.format("Several instancs of %s-Singleton " +
                    "found in database.", class_.getName()));
        else {
            logger.info("Retrieved " + class_.getName() + " instance from Db4o.");
            return objects.next();
        }
    }

    /**
     * Determines whether there is at most one instance of the given class saved in the current default database.
     *
     * @param class_ the class to be checked about singltonness, matches exact class, with no supertype relations
     */
    public static void assertUniqueInDatabase(Class class_) {

        ObjectSet result = currentDatabase().query(class_);
        assert result.size() < 2;
    }
}
